local class = reload("class")
local httpC = require("httpC")
local newt = reload("newt")
local delt = reload("delt")
local delts = reload("delts")
local cjson = require("cjson")
local super = reload("super.basic")

local empty = {}

---@class httpLC:super.basic
local this = class(super)

function this:ctor(name)
    super.ctor(self)
    self._name = name
    self._cook = 0
    self._watch = {}
    self:closure()
end

function this:launch()
    httpC.new(self._name, self)
    return self:hand()
end

function this:hand()
    return function (hand)
        self._hand = hand
    end
end

function this:cook()
    local cook = self._cook
    cook = cook + 1
    self._cook = cook
    return cook
end

function this:closure()
    local watch = self._watch
    self._closure = function (callback, ...)
        ---保存监听信息
        local info = newt()
        watch[self._cook] = info

        ---记录回调函数
        info.f = callback
        ---保存携带参数(用于避免不断产生闭包的情况)
        local vlen = select("#", ...)
        local args = newt()
        info.args = args
        for i = 1, vlen do
            local arg = select(i, ...)
            table.insert(args, arg)
        end
    end
end

function this:reply(cook, method, ret)
    local info = self._watch[cook]
    self._watch[cook] = nil
    if info then
        self:nonepush(info.args, ret)
        ---追加返回参数
        delts(info.f(table.unpack(info.args)))
        ---回收数据
        delt(info.args)
        delt(info)
        return
    end
    local hand = self._hand
    hand[method](ret)
end

function this:nonepush(args, ...)
    local len = select("#", ...)
    for i = 1, len do
        local arg = select(i, ...)
        table.insert(args, arg)
    end
end

function this:watch()
    return self._closure
end

function this:get(url, uri, body, ...)
    local cookid = self:cook()
    body = cjson.encode(body or empty)
    httpC.get(cookid, self._name, url, uri, body, ...)
    return self:watch()
end

function this:post(url, uri, body, ...)
    local cookid = self:cook()
    body = cjson.encode(body or empty)
    httpC.post(cookid, self._name, url, uri, body, ...)
    return self:watch()
end

function this:put(url, uri, body, ...)
    local cookid = self:cook()
    body = cjson.encode(body or empty)
    httpC.put(cookid, self._name, url, uri, body, ...)
    return self:watch()
end

function this:delete(url, uri, body, ...)
    local cookid = self:cook()
    body = cjson.encode(body or empty)
    httpC.delete(cookid, self._name, url, uri, body, ...)
    return self:watch()
end

function this:head(url, uri, body, ...)
    local cookid = self:cook()
    body = cjson.encode(body or empty)
    httpC.head(cookid, self._name, url, uri, body, ...)
    return self:watch()
end

function this:options(url, uri, body, ...)
    local cookid = self:cook()
    body = cjson.encode(body or empty)
    httpC.options(cookid, self._name, url, uri, body, ...)
    return self:watch()
end

return this
